В
индийском храме пол прямоугольной формы выложен одинаковыми квадратными
плитками 1 × 1, на каждую из которых высыпано от 0 до k (k
≤ 30000) зернышек. Размеры пола m × n. Мышка выбегает из левого нижнего угла пола храма и двигается к
входу в другую норку, расположенную в противоположном углу. Мышка может
двигаться только вправо или вперед, собирая все зернышки с плитки, на которой
она находится.
Найти
маршрут, двигаясь по которому мышка соберет наибольшее количество зернышек.
Вход. Первая
строка содержит числа m и n (1 ≤ m, n ≤ 100) – размеры пола. Далее идут m строк, начиная сверху, в каждой из которых размещено чисел –
количество зернышек на соответствующей плитке.
Выход. Вывести
маршрут движения мышки в формате: RRFFFRF (F – шаг вперед, R – шаг вправо).
Пример входа |
Пример выхода |
2 3 3 2 4 1 5 1 |
RFR |
динамическое
программирование
Для
удобства дальнейших вычислений перевернем доску снизу вверх. Клетки по
вертикали и по горизонтали будем нумеровать с 1. Тогда маршрут мышки будет
пролегать с левого верхнего угла – клетки с координатами (1, 1), в правый
нижний – клетку с координатами (m, n). А движение вниз по доске будет
кодироваться буквой F.
Пусть на
плитке с координатами (i, j) находится a[i][j] зернышек. Пусть
res[i][j] содержит максимальное количество зернышек, которое можно собрать
при движении из левого верхнего угла в клетку (i, j). Поскольку на
плитку (i, j) можно попасть или из плитки (i
– 1, j), или из (i, j – 1), то
res[i][j]
= max(res[i – 1][j], res[i][j – 1]) + a[i][j]
Можно
также обойтись и без массива res, совершая вычисления в самом массиве а. Будем
проходить плитки пола (ячейки массива) сверху вниз и слева направо, положив
а[i][j]
= max(a[i – 1][j], a[i][j – 1]) + a[i][j]
Изначально
все ячейки нулевой строки и нулевого столбца массива а инициализируем -1.
Однако для корректного пересчета значения а[1][1] следует обнулить одну из
ячеек: a[0][1] или a[1][0]. В таком случае новое значение ячейки а[1][1] станет
равным max(a[0][1], a[1][0]) + a[1][1] = 0 + a[1][1] = a[1][1]. В дальнейшем
все значения а[i][j] будут пересчитаны корректно.
После проведенных
вычислений a[i][j] уже будет содержать максимальное количество зернышек, которое
можно собрать по достижении плитки (i,
j). Состояние массива а по окончанию
вычислений:
Реализация алгоритма
Входную
информацию о зернышках будем хранить в массиве a. То есть на плитке с
координатами (i, j) находится a[i][j] зернышек. Маршрут движения мышки
будем сохранять в массиве pos, имеющему длину m + n – 1 (m и n – размеры пола).
#define MAX 102
int a[MAX][MAX];
char pos[2*MAX];
Считываем
входные данные. Поскольку на плитках может находиться и 0 зернышек, то
инициализируем ячейки массива числами -1. Доску переворачиваем снизу вверх.
scanf("%d %d",&m,&n);
memset(a,-1,sizeof(a));
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
scanf("%d",&a[m-i+1][j]);
Пересчитаем ячейки массива а так,
чтобы а[i][j] содержало максимальное количество
зернышек, которое можно собрать по достижении плитки (i, j).
a[0][1] = 0;
for(i = 1; i <= m; i++)
for(j = 1; j <= n; j++)
a[i][j] =
max(a[i-1][j],a[i][j-1]) + a[i][j];
Начиная
с плитки (i, j) = (m, n), двигаемся до
плитки (1, 1) записывая маршрут движения мышки в массиве pos. Из плитки (i, j)
необходимо двигаться в (i – 1, j) или (i, j – 1), в зависимости
от того, какое из значений a[i – 1][j] или a[i][j
– 1] больше.
i = m; j = n; ptr = 0;
while(i + j > 2)
{
if (a[i-1][j] > a[i][j-1])
{
pos[ptr] = 'F';
i--;
}
else
{
pos[ptr] = 'R';
j--;
}
ptr++;
}
Выводим
маршрут движения мышки.
while(ptr--) printf("%c",pos[ptr]);
printf("\n");